package com.ibis.debuglistwidget;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import java.util.ArrayList;

/**
 * A dummy class that we are going to use internally to store Log data.
 * Generally, this data will be stored in an external and persistent location
 * (ie. File, Database, SharedPreferences) so that the data can persist if the
 * process is ever killed. For simplicity, in this sample the data will only be
 * stored in memory.
 */

/**
 * The AppWidgetProvider for our sample Log widget.
 */
public class LogDataProvider extends ContentProvider {
    public static final Uri CONTENT_URI = Uri
            .parse("content://com.ibis.debuglistwidget.provider");

    public static class Columns {
        public static final String ID = "_id";
        // public static final String LOG = "log";
        public static final String TEXT = "text";
        // public static final String TEMPERATURE = "temperature";
        public static final String LEVEL = "level";
        public static final String COLOR = "color";
    }

    // private static class State {
    // List<LogEntry> entries = null;
    // boolean play = true;
    // int position = -1;
    // }

    private static final String TAG = LogDataProvider.class.getSimpleName();

    /**
     * Generally, this data will be stored in an external and persistent
     * location (ie. File, Database, SharedPreferences) so that the data can
     * persist if the process is ever killed. For simplicity, in this sample the
     * data will only be stored in memory.
     */
    public static final ArrayList<LogEntry> sData = new ArrayList<LogEntry>();
    private static final int WINDOW_SIZE = 100;
    private Level mLastLevel = Level.V;
    private Logcat mLogcat;
    private Prefs mPrefs;
    // private LogDataProvider mThis;
    private boolean mPlay = true;
//    private SharedPreferences sharedPreferences;

    private Handler mHandler = new Handler() {
        /*
         * (non-Javadoc)
         *
         * @see android.os.Handler#handleMessage(android.os.Message)
         */
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case Logcat.CAT_WHAT:
                    final String line = (String) msg.obj;

                    // Keeping data's size at WINDOW_SIZE
                    if (sData.size() >= WINDOW_SIZE) {
                        sData.remove(0);
                    }

                    cat(line);
//                    sData.add(new LogEntry(line));
                    // sData.add(new LogEntry(line, sData.size()));
                    // Log.d(TAG, "CAT_WHAT");

                    break;
                case Logcat.CLEAR_WHAT:

                    sData.clear();
                    Log.d(TAG, "CLEAR_WHAT");
                    break;
            }
        }
    };

    @Override
    public boolean onCreate() {
        Log.d(TAG, "onCreate");
        // mThis = this;


        mPrefs = new Prefs(getContext());

        reset();

        return true;
    }

    public void reset() {
        Log.d(TAG, "reset");

        // Context otherAppsContext = null;
        // try {
        // otherAppsContext = createPackageContext(
        // "com.faynasoftlabs.tutorial.android.sharedpreferences", 0);
        // } catch (NameNotFoundException e) {
        // }

        // sharedPreferences = PreferenceManager
        // .getDefaultSharedPreferences(getContext());

        // Toast.makeText(this, R.string.reading_logs,
        // Toast.LENGTH_LONG).show();
        mLastLevel = Level.V;

        if (mLogcat != null) {
            Log.d(TAG, "mLogcat.stop()");
            mLogcat.stop();
        }

        mPlay = true;
        new Thread(new Runnable() {
            public void run() {
                Log.d(TAG, "mLogcat.start()");
                mLogcat = new Logcat(getContext(), mHandler);
                mLogcat.start();
            }
        }).start();
        // Thread.setPriority(Thread.MIN_PRIORITY)
    }

    private void cat(final String s) {
        // if (mLogEntryAdapter.getCount() > WINDOW_SIZE) {
        // mLogEntryAdapter.remove(0);
        // }

        Format format = mPrefs.getFormat();
        Level level = format.getLevel(s);
        if (level == null) {
            level = mLastLevel;
        } else {
            mLastLevel = level;
        }

        final LogEntry entry = new LogEntry(s, level);
        sData.add(entry);

        // if (mPrefs.isAutoScroll() && tailing) {
        // jumpBottom();
        // }
    }

    @Override
    public synchronized Cursor query(Uri uri, String[] projection,
                                     String selection, String[] selectionArgs, String sortOrder) {
        assert (uri.getPathSegments().isEmpty());
        Log.d(TAG, "query");
        // In this sample, we only query without any parameters, so we can just
        // return a cursor to
        // all the Log data.
        final MatrixCursor c = new MatrixCursor(new String[]{Columns.ID,
                Columns.TEXT , Columns.COLOR
        });
        int j = sData.size();
        Log.d(TAG, "query" + j);

        for (int i = 0; i < sData.size(); i++) {
            j--;

            final LogEntry data = sData.get(j);
            // final LogDataPoint data = sData.get(i);
            c.addRow(new Object[]{new Integer(i), new String(data.getText())
                     , new Integer(data.getLevel().getColor())
            });
        }
        // }
        Log.d(TAG, "query|return");
        return c;
    }

    @Override
    public String getType(Uri uri) {
        return "vnd.android.cursor.dir/vnd.loglistwidget.logs";
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        // This example code does not support inserting
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // This example code does not support deleting
        return 0;
    }

    @Override
    public synchronized int update(Uri uri, ContentValues values,
                                   String selection, String[] selectionArgs) {
        // assert (uri.getPathSegments().size() == 1);
        Log.d(TAG, "update");
        // In this sample, we only update the content provider individually for
        // each row with new
        // temperature values.
        // final int index = Integer.parseInt(uri.getPathSegments().get(0));
        // final MatrixCursor c = new MatrixCursor(new String[] { Columns.ID,
        // Columns.TEXT
        // , Columns.LEVEL
        // });
        // assert (0 <= index && index < sData.size());
        // final LogEntry data = sData.get(index);
        // data.degrees = values.getAsInteger(Columns.TEMPERATURE);
        // data.setText(values.getAsString(Columns.TEXT));
        // Log.d(TAG, data.log);
        // Notify any listeners that the data backing the content provider has
        // changed, and return
        // the number of rows affected.
        Log.d(TAG, "update|notifyChange");
        getContext().getContentResolver().notifyChange(uri, null);
        return 1;
    }

    // private LogDataProvider.State getState() {
    // State state = new State();
    //
    // // state.entries = mLogEntryAdapter.getLogEntries();
    // state.play = mPlay;
    // // int x = mLogList.getScrollX();
    // // int y = mLogList.getScrollY();
    // // state.position = mLogList.pointToPosition(x, y);
    //
    // return state;
    // }
    //
    // private void setState(final LogDataProvider.State state) {
    // if (state != null) {
    // if (!state.play) {
    // // mLogEntryAdapter = new LogEntryAdapter(this, R.layout.entry,
    // // state.entries);
    // // setListAdapter(mLogEntryAdapter);
    // mPlay = false;
    // }
    // // mLogList.post(new Runnable() {
    // // public void run() {
    // // synchronized (LogActivity.this) {
    // // mLogList.setSelection(state.position);
    // // }
    // // }
    // // });
    // }
    // }
}